package com.serial.comm.config.rabbitmq;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.serial.comm.config.redis.RedisService;
import com.serial.comm.core.constants.RabbitConst;
import com.serial.comm.core.constants.RedisConstants;
import com.serial.comm.core.rest.fodb.FODBRestClient;
import com.serial.comm.core.utils.ValueUtils;
import com.serial.comm.modular.serialPort.enums.FODBEnums;
import com.serial.comm.modular.serialPort.enums.TelegramEnum;
import com.serial.comm.modular.serialPort.model.Origin;
import com.serial.comm.modular.serialPort.model.TelegramIllegal;
import com.serial.comm.modular.serialPort.model.TelegramMQ;
import com.serial.comm.modular.serialPort.service.IOriginService;
import com.serial.comm.modular.serialPort.service.ITelegramIllegalService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.UUID;

/**
 * 串口死信队列 消费者
 */
@Component
public class DeadLetterMessageReceiver {

    public static Logger log = LoggerFactory.getLogger(DeadLetterMessageReceiver.class);


    @Resource
    private FODBRestClient fodbRestClient;

    @Resource
    private SerialMsgSender serialMsgSender;

    @Resource
    private RedisService redisService;

    @Resource
    private IOriginService originService;

    @Resource
    private ITelegramIllegalService telegramIllegalService;

    /**
     * 串口读取 原始电报 死信消费者
     *
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(queues = RabbitConst.DEAD_LETTER_QUEUE_BASE_READ)
    public void receiveBaseReadQueue(Message message, Channel channel) throws IOException {
        String msg = new String(message.getBody());
        log.info(">>>>>>读取-死信队列收到原始电报消息：" + msg);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        Origin origin = new Origin(msg, TelegramEnum.FAILED.getCode(), TelegramEnum.READ.getCode(), UUID.randomUUID().toString());
        Integer sourceId = originService.createOriginTelegramAndGetId(origin);
        log.info(">>>>>>读取-异常原始电报已入库,id:{}", sourceId);
    }

    /**
     * 串口读取 单一电报 死信消费者
     *
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(queues = RabbitConst.DEAD_LETTER_QUEUE_UNITARY_READ)
    public void receiveUnitaryReadQueue(Message message, Channel channel) throws IOException {
        String messageId = message.getMessageProperties().getMessageId();
        String exceptionReason = ValueUtils.parseString(redisService.getValue(RedisConstants.TELEGRAM_EXCEPTION_REASON + messageId));
        String msg = new String(message.getBody());
        log.info(">>>>>>读取-死信队列收到单一电报消息：" + msg);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        //异常单一电报处理 ： 携带 异常理由 和 sourceId入库保存
        TelegramMQ mqMsg = JSON.parseObject(msg, TelegramMQ.class);
        Integer sourceId = mqMsg.getSourceId();
        TelegramIllegal telegramIllegal = new TelegramIllegal(exceptionReason, sourceId, mqMsg.getTelegramText());

        telegramIllegalService.insert(telegramIllegal);
        log.info(">>>>>>读取-异常单一电报已入库,异常原因：【{}】", exceptionReason);

    }


    /**
     * 串口写入 死信消费者
     *
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(queues = RabbitConst.DEAD_LETTER_QUEUE_WRITE)
    @RabbitHandler
    public void receiveWriteQueue(@Payload TelegramMQ telegramMQ, Message message, Channel channel) throws IOException {
        String msg = telegramMQ.getTelegramText();
        log.info(">>>>>>写入-死信队列收到消息：" + JSON.toJSONString(msg));
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        Origin origin = new Origin(msg, TelegramEnum.FAILED.getCode(), TelegramEnum.WRITE.getCode(), telegramMQ.getGuid());
        originService.createOriginTelegramAndGetId(origin);
        log.info(">>>>>>写入-异常电报已入库");

        log.info(">>>>>>准备通知fodb写入结果");
        String result = fodbRestClient.fodbRequireApi(FODBEnums.WRITE_FAILED.getMessage(), FODBEnums.WRITE_FAILED.getCode(), origin.getGuid());
        log.info("已通知fodb写入结果，FODB写入接口返回值:{}", JSON.toJSONString(result));


    }

    /**
     * 串口写入重试 死信队列消费者
     *
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(queues = RabbitConst.DEAD_LETTER_QUEUE_WRITE_RETRY)
    @RabbitHandler
    public void receiveWriteRetryQueue(@Payload TelegramMQ telegramMQ, Message message, Channel channel) throws IOException {
        log.info(">>>>>>重试-死信队列收到消息：" + JSON.toJSONString(telegramMQ.getTelegramText()));
        //手动签收
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        serialMsgSender.sendWriteQueueMsg(telegramMQ);
    }
}
